package com.ljj.examisto.ui.activity

import android.annotation.SuppressLint
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.database.Cursor
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.ljj.examisto.R
import com.ljj.examisto.data.item.RemindType
import com.ljj.examisto.data.item.Reminder
import com.ljj.examisto.databinding.ActivityEditExamBinding
import com.ljj.examisto.ui.activity.HomeActivity.Companion.backHome
import com.ljj.examisto.ui.dialog.AddRemindDialog
import com.ljj.examisto.util.DatabaseHelper
import com.ljj.examisto.util.ExamContract
import com.ljj.examisto.util.Logger.TAG
import com.ljj.examisto.util.RemindOptionProvider
import com.ljj.examisto.util.RemindOptionProvider.remindOptions
import com.ljj.examisto.util.ReminderContract
import com.ljj.examisto.ui.dialog.ScrollingTimePickerDialog
import com.ljj.examisto.util.ToastManager
import java.util.Calendar
import kotlin.properties.Delegates

class EditExamActivity : AppCompatActivity(), AddRemindDialog.OnConfirmListener {
    companion object {
        fun start(context: Context, examName: String) {
            val intent = Intent(context, EditExamActivity::class.java)
            intent.putExtra("EXAM_NAME", examName)
            context.startActivity(intent)
        }
    }

    private lateinit var binding: ActivityEditExamBinding
    private lateinit var dbHelper: DatabaseHelper
    private lateinit var prefs: SharedPreferences
    private var examName: String = ""
    private var location: String = ""
    private var is24HourFormat by Delegates.notNull<Boolean>()
    private var selectedYear: Int = 0
    private var selectedMonth: Int = 0
    private var selectedDay: Int = 0
    private var selectedHour: Int = 0
    private var selectedMinute: Int = 0
    private var startTime: Long =  0
    private var duration: Int = 0
    private var remark: String = ""
    private var exam: Cursor? = null
    private var reminders: MutableList<Reminder> = mutableListOf()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initProperty()
        setupViews()
    }

    override fun onRemindConfirmed(reminder: Reminder) {
        reminders.add(reminder)
        updateRemindersDisplay()
    }

    /* 流程函数 */
    private fun initProperty() {
        binding = ActivityEditExamBinding.inflate(layoutInflater)
        dbHelper = DatabaseHelper.getInstance(this)
        prefs = getSharedPreferences(getString(R.string.app_preference_name), MODE_PRIVATE)
        examName = intent.getStringExtra("EXAM_NAME").toString()
        exam = dbHelper.getExamByName(examName)
        reminders = dbHelper.getRemindersByName(examName).use { cursor ->
            val list = mutableListOf<Reminder>()
            if (cursor != null) {
                do {
                    val value = cursor.getInt(cursor.getColumnIndexOrThrow(ReminderContract.COLUMN_SECONDS))
                    val type = RemindType.fromString(cursor.getString(cursor.getColumnIndexOrThrow(ReminderContract.COLUMN_TYPE)))
                    list.add(Reminder(value, type))
                }
                while (cursor.moveToNext())
            }
            list
        }
        is24HourFormat = prefs.getBoolean(getString(R.string.key_is_24_hour_format), true)
    }

    private fun setupViews() {
        setContentView(binding.root)
        setupCancelButton()
        setupSaveButton()
        setupExamShower()
        setupEditButton()
        setupDeleteButton()
        setupAddReminderButton()
        updateRemindersDisplay()
        setupEnableForRemindArea()
    }

    private fun setupExamShower() {
        getExamInfo()
        setupExamNameTextView()
        setupLocationEditText()
        setupTimeFormatSwitch()
        setupDateButton()
        setupTimeButton()
        setupDurationButton()
        setupRemarkEditText()
    }

    /* 工具函数 */
    @SuppressLint("ClickableViewAccessibility")
    private fun setupCancelButton() {
        binding.btnCancel.setOnTouchListener { view, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    binding.btnCancel.setBackgroundResource(R.drawable.ic_cancel_pressed)
                    true
                }
                MotionEvent.ACTION_MOVE -> {
                    if (!isTouchInsideView(view, event)) {
                        binding.btnCancel.setBackgroundResource(R.drawable.ic_cancel)
                    }
                    true
                }
                MotionEvent.ACTION_UP -> {
                    binding.btnCancel.setBackgroundResource(R.drawable.ic_cancel)
                    if (isTouchInsideView(view, event)) {
                        backHome(this)
                    }
                    true
                }
                MotionEvent.ACTION_CANCEL -> {
                    binding.btnCancel.setBackgroundResource(R.drawable.ic_cancel)
                    true
                }
                else -> false
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun setupSaveButton() {
        binding.btnSave.setBackgroundResource(R.drawable.ic_save_pressed)
        binding.btnSave.setOnTouchListener { view, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    binding.btnSave.setBackgroundResource(R.drawable.ic_save_pressed)
                    true
                }
                MotionEvent.ACTION_MOVE -> {
                    if (!isTouchInsideView(view, event)) {
                        binding.btnSave.setBackgroundResource(R.drawable.ic_save)
                    }
                    true
                }
                MotionEvent.ACTION_UP -> {
                    binding.btnSave.setBackgroundResource(R.drawable.ic_save)
                    if (isTouchInsideView(view, event)) {
                        if (updateExamInfo()) {
                            ToastManager.interruptedToast(this, "已修改", Toast.LENGTH_SHORT)
                        } else {
                            ToastManager.interruptedToast(this, "修改失败", Toast.LENGTH_SHORT)
                        }
                        backHome(this)
                    }
                    true
                }
                MotionEvent.ACTION_CANCEL -> {
                    binding.btnSave.setBackgroundResource(R.drawable.ic_save)
                    true
                }
                else -> false
            }
        }
    }

    private fun getExamInfo() {
        exam?.use { cursor ->
            try {
                location = cursor.getString(cursor.getColumnIndexOrThrow(ExamContract.COLUMN_LOCATION))
                startTime = cursor.getLong(cursor.getColumnIndexOrThrow(ExamContract.COLUMN_START_TIME))
                duration = cursor.getInt(cursor.getColumnIndexOrThrow(ExamContract.COLUMN_DURATION))
                remark = cursor.getString(cursor.getColumnIndexOrThrow(ExamContract.COLUMN_REMARK))
                val timeStr = startTime.toString()
                selectedYear = timeStr.substring(0, 4).toInt()
                selectedMonth = timeStr.substring(4, 6).toInt() - 1
                selectedDay = timeStr.substring(6, 8).toInt()
                selectedHour = timeStr.substring(8, 10).toInt()
                selectedMinute = timeStr.substring(10, 12).toInt()
            } catch (e: IllegalArgumentException) {
                Log.e(TAG, "setupExamShower: 列名无效", e)
                binding.tvExamName.text = ""
            } catch (e: Exception) {
                Log.e(TAG, "setupExamShower: 未知错误", e)
                binding.tvExamName.text = ""
            }
        }
    }

    private fun setupExamNameTextView() {
        binding.tvExamName.text = examName
    }

    private fun setupLocationEditText() {
        binding.etLocation.setText(location)
    }

    private fun setupTimeFormatSwitch() {
        binding.switchTimeFormat.setTextColor(ContextCompat.getColor(this, R.color.text_color_disabled))
        binding.switchTimeFormat.isChecked = is24HourFormat
        updateTimeFormatText()
        binding.switchTimeFormat.setOnCheckedChangeListener { _, isChecked ->
            is24HourFormat = isChecked
            updateTimeFormatText()
            updateTimeDisplay()
        }
    }

    private fun setupDateButton() {
        binding.btnDate.setTextColor(ContextCompat.getColor(this, R.color.text_color_disabled))
        updateDateDisplay()
        binding.btnDate.setOnClickListener {
            val currentCalendar = Calendar.getInstance() // 获取当前日期
            val minDate = currentCalendar.timeInMillis // 当前日期的毫秒时间戳
            DatePickerDialog(
                this,
                { _, year, month, day ->
                    // 用户选择的日期
                    val selectedCalendar = Calendar.getInstance().apply {
                        set(year, month, day)
                    }

                    // 检查选择的日期是否 >= 今天
                    if (selectedCalendar.timeInMillis >= minDate) {
                        selectedYear = year
                        selectedMonth = month
                        selectedDay = day
                        updateDateDisplay()
                    } else {
                        // 如果选择的是过去的日期，提示用户
                        ToastManager.interruptedToast(this, "不能选择过去的日期", Toast.LENGTH_SHORT)
                    }
                },
                selectedYear, selectedMonth, selectedDay
            ).apply {
                // 设置日期选择器的最小日期为今天
                datePicker.minDate = minDate
            }.show()
        }
    }

    private fun setupTimeButton() {
        binding.btnTime.setTextColor(ContextCompat.getColor(this, R.color.text_color_disabled))
        updateTimeDisplay()
        binding.btnTime.setOnClickListener {
            val currentCalendar = Calendar.getInstance() // 获取当前时间
            val currentTimeInMillis = currentCalendar.timeInMillis // 当前时间的毫秒时间戳
            // 用户之前选择的日期（在 setupDateButton 中设置）
            val selectedDateCalendar = Calendar.getInstance().apply {
                set(selectedYear, selectedMonth, selectedDay)
            }

            TimePickerDialog(
                this,
                { _, hour, minute ->
                    // 用户选择的时间
                    val selectedDateTimeCalendar = Calendar.getInstance().apply {
                        set(selectedYear, selectedMonth, selectedDay, hour, minute)
                    }

                    // 检查选择的日期是否是今天
                    val isToday = selectedDateCalendar.get(Calendar.DAY_OF_YEAR) ==
                            currentCalendar.get(Calendar.DAY_OF_YEAR) &&
                            selectedDateCalendar.get(Calendar.YEAR) ==
                            currentCalendar.get(Calendar.YEAR)

                    if (!isToday || selectedDateTimeCalendar.timeInMillis >= currentTimeInMillis) {
                        // 如果不是今天，或者时间 >= 当前时间，允许选择
                        selectedHour = hour
                        selectedMinute = minute
                        updateTimeDisplay()
                    } else {
                        // 如果是今天且时间早于当前时间，提示用户
                        ToastManager.interruptedToast(this, "不能选择过去的时间", Toast.LENGTH_SHORT)
                    }
                },
                selectedHour,
                selectedMinute,
                is24HourFormat
            ).show()
        }
    }

    @SuppressLint("SetTextI18n")
    private fun setupDurationButton() {
        binding.btnDuration.setTextColor(ContextCompat.getColor(this, R.color.text_color_disabled))
        updateDurationDisplay()
        binding.btnDuration.setOnClickListener {
            ScrollingTimePickerDialog(this) { hour, minute ->
                duration = hour * 60 + minute
                updateDurationDisplay()
            }.apply {
                setDefaultTime(duration / 60, duration % 60)
            }.show()
        }
    }

    private fun setupRemarkEditText() {
        binding.etRemark.setText(remark)
    }

    // 点击编辑按钮组件效果发生变化
    private fun setupEditButton() {
        binding.btnEdit.setOnClickListener {
            binding.btnSave.setBackgroundResource(R.drawable.ic_save)
            binding.btnEdit.setTextColor(ContextCompat.getColor(this, R.color.text_color_disabled))
            binding.switchTimeFormat.setTextColor(ContextCompat.getColor(this, R.color.text_color))
            binding.btnDate.setTextColor(ContextCompat.getColor(this, R.color.text_color))
            binding.btnTime.setTextColor(ContextCompat.getColor(this, R.color.text_color))
            binding.btnDuration.setTextColor(ContextCompat.getColor(this, R.color.text_color))
            binding.fblRemind.setEnabledRecursively(true)
            binding.btnSave.isEnabled = true
            binding.etLocation.isEnabled = true
            binding.switchTimeFormat.isEnabled = true
            binding.btnDate.isEnabled = true
            binding.btnTime.isEnabled = true
            binding.btnDuration.isEnabled = true
            binding.etRemark.isEnabled = true
            binding.btnEdit.isEnabled = false
        }
    }

    private fun setupDeleteButton() {
        binding.btnDelete.setOnClickListener {
            AlertDialog.Builder(this)
                .setTitle("删除确认")
                .setMessage("是否确认删除此考试的信息")
                .setPositiveButton("确认") { dialog, _ ->
                    if (dbHelper.deleteExamWithReminders(examName)) {
                        ToastManager.interruptedToast(this, "已删除", Toast.LENGTH_SHORT)
                    } else {
                        ToastManager.interruptedToast(this, "删除失败", Toast.LENGTH_SHORT)
                    }
                    dialog.dismiss()
                    backHome(this)
                }
                .setNegativeButton("取消", null)
                .show()
        }
    }

    private fun setupAddReminderButton() {
        binding.btnAddReminder.setOnClickListener {
            if (remindOptions.all { option -> reminders.any { it.value == option.value } }) {
                ToastManager.interruptedToast(this, "已添加所有提醒选项", Toast.LENGTH_SHORT)
            } else {
                val dialog = AddRemindDialog(this, reminders)
                dialog.setOnConfirmListener(this)
                dialog.show()
            }
        }
    }

    private fun setupEnableForRemindArea() {
        binding.fblRemind.setEnabledRecursively(false)
    }

    // 扩展函数：为 View 添加递归启用/禁用功能
    private fun View.setEnabledRecursively(enabled: Boolean) {
        isEnabled = enabled
        alpha = if (enabled) 1.0f else 0.8f
        if (this is ViewGroup) {
            for (i in 0 until childCount) {
                getChildAt(i).setEnabledRecursively(enabled)
            }
        }
    }

    private fun updateTimeFormatText() {
        binding.switchTimeFormat.text = getString(
            if (is24HourFormat) R.string.hint_time_format_24h
            else R.string.hint_time_format_12h
        )
        binding.tvStartTime.text = getString(
            if (is24HourFormat) R.string.hint_start_time_24h
            else R.string.hint_start_time_12h
        )
    }

    private fun updateDateDisplay() {
        binding.btnDate.text = getString(
            R.string.date_format,
            selectedMonth + 1,
            selectedDay
        )
    }

    private fun updateTimeDisplay() {
        binding.btnTime.text = if (is24HourFormat) {
            getString(R.string.time_24h_format, selectedHour, selectedMinute)
        } else {
            // 12小时制时段判断
            val (periodResId, displayHour) =
                when (selectedHour) {
                    0 -> R.string.time_midnight to 12                                   // 半夜12:00
                    in 1..5 -> R.string.time_midnight to selectedHour             // 半夜1:00-5:59
                    in 6..8 -> R.string.time_morning to selectedHour             // 早上6:00-8:59
                    in 9..11 -> R.string.time_forenoon to selectedHour            // 上午9:00-11:59
                    12 -> R.string.time_afternoon to 12                                  // 下午12:00
                    in 13..17 -> R.string.time_afternoon to selectedHour - 12      // 下午1:00-5:59
                    in 18..23 -> R.string.time_evening to selectedHour - 12      // 晚上6:00-11:59
                    else -> R.string.time_forenoon to selectedHour                      // 异常回退
                }
            getString(periodResId, displayHour, selectedMinute)
        }
    }

    @SuppressLint("SetTextI18n")
    private fun updateDurationDisplay() {
        binding.btnDuration.text = "${duration}分钟"
    }

    private fun updateExamInfo(): Boolean {
        examName = binding.tvExamName.text.toString()
        location = binding.etLocation.text.toString()
        startTime = createStartTime(selectedYear, selectedMonth + 1, selectedDay, selectedHour, selectedMinute)
        remark = binding.etRemark.text.toString()
        if (duration <= 0) {
            ToastManager.interruptedToast(this, "请设置考试时长", Toast.LENGTH_SHORT)

        }
        if (dbHelper.checkTimeConflict(examName, startTime, duration)) {
            ToastManager.interruptedToast(this, "添加的考试和其它考试的时间有冲突", Toast.LENGTH_SHORT)
            return false
        }
        val result1 = dbHelper.updateExam(examName, location, startTime, duration, remark)
        val result2 = dbHelper.updateReminders(examName, startTime, reminders)
        if (!result1) {
            Log.e(TAG, "更新考试信息失败")
            return false
        } else if (!result2) {
            Log.e(TAG, "插入提醒序列失败")
            return false
        } else {
            Log.d(TAG, "考试信息更新成功，名称: $examName")
            return true
        }
    }

    private fun updateRemindersDisplay() {
        val remindLayout = binding.fblRemind
        val addReminderButton = binding.btnAddReminder
        // 清空
        for (i in remindLayout.childCount - 1 downTo 0) {
            val child = remindLayout.getChildAt(i)
            if (child !== addReminderButton) {
                remindLayout.removeViewAt(i)
            }
        }
        // 添加
        val sortedReminders = reminders.sortedBy { it.value }
        sortedReminders.forEach { reminder ->
            val title = "考试前${secondsToString(reminder.value)}"
            val reminderView = LayoutInflater.from(this).inflate(
                R.layout.reminder_displayer, remindLayout, false
            )
            val remindTypeIcon = reminderView.findViewById<ImageView>(R.id.iv_remind_type)
            val remindTitle = reminderView.findViewById<TextView>(R.id.tv_remind_title)
            val cancelRemindButton = reminderView.findViewById<Button>(R.id.btn_cancel_remind)
            remindTypeIcon.setBackgroundResource(
                when (reminder.type) {
                    RemindType.NOTIFICATION -> R.drawable.ic_notification
                    RemindType.ALARM -> R.drawable.ic_alarm
                }
            )
            remindTitle.text = title
            cancelRemindButton.setOnClickListener {
                reminders.remove(reminder)
                updateRemindersDisplay()
            }
            remindLayout.addView(reminderView)
        }
    }

    @SuppressLint("DefaultLocale")
    private fun createStartTime(year: Int, month: Int, day: Int, hour: Int, minute: Int): Long {
        val startTimeString = String.format("%04d%02d%02d%02d%02d", year, month, day, hour, minute)
        return startTimeString.toLong()
    }

    private fun isTouchInsideView(view: View, event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y
        return x >= 0 && x <= view.width && y >= 0 && y <= view.height
    }

    private fun secondsToString(seconds: Int): String {
        return RemindOptionProvider.findNameByValue(seconds)
    }
}